package com.jasperframework.boot.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.apache.hc.core5.util.Timeout;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static org.apache.hc.core5.http.HttpStatus.SC_OK;

/**
 * <p> apache httpClient5 工具类</p>
 *
 * @author: daizhao 12:29 2025/1/9 0009
 */
@Slf4j
public class ApacheHttpClient5Util {

    public static String doHttpGet(String url, Map<String, String> params, int timeout, String encode, List<Header> headers){
        String responseMsg = "";
        // 使用 try-with-resources 自动关闭 HttpClient 和 HttpResponse
        try (CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(RequestConfig.custom().setMaxRedirects(3)
                        .setConnectionRequestTimeout(Timeout.ofSeconds(timeout))
                        .setResponseTimeout(Timeout.ofSeconds(timeout))
                        .build())
                .build()) {
            // 构建 GET 请求
            if (params != null && !params.isEmpty()) {
                StringBuilder paramBuilder = new StringBuilder();
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    // 判断编码是否为空
                    if (encode != null && !encode.isEmpty()) {
                        // 使用 URLEncoder 对参数进行编码
                        key = URLEncoder.encode(key, encode);
                        value = URLEncoder.encode(value, encode);
                    }
                    paramBuilder.append(key).append("=").append(value).append("&");
                }
                url = url + "?" + paramBuilder.substring(0, paramBuilder.length() - 1);
            }

            HttpGet httpGet = new HttpGet(url);

            if (headers != null && !headers.isEmpty()) {
                for (Header header : headers) {
                    httpGet.addHeader(header);
                }
            }
            // 使用 HttpClientResponseHandler 处理响应
            responseMsg = httpClient.execute(httpGet, response -> {
                if (response.getCode() == SC_OK) {
                    return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                } else {
                    throw new IOException("Unexpected response code: " + response.getCode());
                }
            });
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return responseMsg;
    }

    public static String doHttpGet(String url, Map<String, String> params, int timeout, String encode) {
        return doHttpGet(url, params, timeout, encode, null);
    }

    public static String doHttpGet(String url, Map<String, String> params, int timeout) {
        return doHttpGet(url, params, timeout, null, null);
    }

    public static String doHttpPost(String url, Map<String, Object> params, int timeout, String encode, List<Header> headers) {
        String responseMsg = "";
        // 使用 try-with-resources 自动关闭 HttpClient 和 HttpResponse
        try (CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(RequestConfig.custom()
                        .setConnectionRequestTimeout(Timeout.ofSeconds(timeout))
                        .setResponseTimeout(Timeout.ofSeconds(timeout))
                        .build())
                .build()) {

            HttpPost httpPost = new HttpPost(url);
            if (params != null && !params.isEmpty()) {
                List<NameValuePair> nameValuePairs = new ArrayList<>();
                for (Map.Entry<String, Object> entry : params.entrySet()) {
                    nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
                }
                httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, StandardCharsets.UTF_8));
            }
            if (headers != null && !headers.isEmpty()) {
                for (Header header : headers) {
                    httpPost.addHeader(header);
                }
            }
            // 使用 HttpClientResponseHandler 处理响应
            responseMsg = httpClient.execute(httpPost, response -> {
                if (response.getCode() == SC_OK) {
                    return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                } else if (response.getCode() == 301 || response.getCode() == 302) {
                    // 处理重定向
                    String newUrl = response.getHeader("Location").getValue();
                    // 这里可以选择是否自动跟随重定向
                    return doHttpPost(newUrl, params, timeout, encode, headers); // 递归调用
                } else {
                    throw new IOException("Unexpected response code: " + response.getCode());
                }
            });
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return responseMsg;
    }
}
